/*
 * A simple ToDo Manager
 *
 * Copyright (c) 2011 Nosheen Zaza, Manuel Rebollo, Seyedsaeid Mahpeikar and
 * Wo Ke
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

package todomanager.ui.tableview;

import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.ResourceBundle;
import javax.swing.AbstractAction;
import javax.swing.AbstractCellEditor;
import javax.swing.ImageIcon;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTable;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.table.TableCellEditor;
import todomanager.model.Task;
import todomanager.model.TaskManager;
import todomanager.ui.ActionControl;

/**
 * The editor of a table that is used to show tasks. It edits {@code Task}
 * objects.
 *
 * @author Nosheen Zaza
 */
public class TaskCellEditor extends AbstractCellEditor implements TableCellEditor {

    /**
     * Edits a tasks status, priority, progress, and data, and allows 
     * deleting a task.
     */
    private TaskDisplayCellComponent taskDisplay;
    private JComboBox category;
    private JComboBox priority;
    private JPanel categoryPanel;
    private JPanel priorityPanel;
    private Task task;
    private ResourceBundle settings;

    public TaskCellEditor() {
        settings = ActionControl.getInstance().getStringsBundle();
        taskDisplay = new TaskDisplayCellComponent();

        String[] categories = settings.getString("Categories").split(",");
        category = new JComboBox(categories);
        category.setOpaque(false);

        categoryPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        categoryPanel.add(category);
        categoryPanel.setOpaque(false);

        String[] priorities = settings.getString("Priorities").split(",");
        priority = new JComboBox(priorities);     
        priority.setOpaque(false);

        priorityPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
        priorityPanel.add(priority);
        priorityPanel.setOpaque(false);

        taskDisplay.getDeleteButton().setAction(new DeleteTaskAction());

        /**
         * When editing stops, apply changes to the model.
         */
        this.addCellEditorListener(new CellEditorListener() {

            public void editingStopped(ChangeEvent e) {
                TaskCellEditor tce = (TaskCellEditor) e.getSource();
                if (TaskManager.getInstance().getTaskList().contains(task)) {
                    TaskManager.getInstance().editTaskText(task,
                            tce.taskDisplay.getCheckTextField().getTextfield().getText());
                    TaskManager.getInstance().editTaskStatus(task,
                            tce.taskDisplay.getCheckTextField().getCheckBox().isSelected());
                    TaskManager.getInstance().editTaskCategory(task,
                            (String) tce.category.getItemAt(tce.category.getSelectedIndex()));
                    TaskManager.getInstance().editTaskPriority(task,
                            (String) tce.priority.getItemAt(tce.priority.getSelectedIndex()));
                    TaskManager.getInstance().editTaskProgress(task,
                            tce.taskDisplay.getProgressMeter().getProgressBar().getValue());
                    if (taskDisplay.getDateChooser().getCalendar() != null
                            && taskDisplay.getDateChooser().getDate() != null) {
                        TaskManager.getInstance().editTaskDate(task,
                                taskDisplay.getDateChooser().getCalendar().get(Calendar.YEAR),
                                taskDisplay.getDateChooser().getCalendar().get(Calendar.MONTH),
                                taskDisplay.getDateChooser().getCalendar().get(Calendar.DATE));
                    } else {
                        TaskManager.getInstance().removeTaskDate(task);
                    }
                }
            }

            public void editingCanceled(ChangeEvent e) {
            }
        });
    }

    /**
     * Returns a suitable editor to a table cell.
     *
     * @param table
     * @param value
     * @param isSelected
     * @param row
     * @param column
     * 
     * @return suitable editor to a table cell, based on column number.
     */
    public Component getTableCellEditorComponent(JTable table, Object value,
            boolean isSelected, int row, int column) {

        // Create a task with the most recent data.
        task = (Task) value;
        taskDisplay.updateData(task, true);
        category.setSelectedItem(task.getCategory());
        priority.setSelectedItem(task.getPriority());

        // Return a suitable editor based on the column.
        if (column == 0) {
            return taskDisplay;
        } else if (column == 1) {
            return categoryPanel;
        } else {
            return priorityPanel;
        }
    }

    /**
     * Returns the most recent cell value.
     * @return task.
     */
    public Object getCellEditorValue() {
        task.setCategory((String) category.getItemAt(category.getSelectedIndex()));
        task.setText(taskDisplay.getCheckTextField().getTextfield().getText());
        task.setPriority((String) priority.getItemAt(priority.getSelectedIndex()));
        task.setProgress(taskDisplay.getProgressMeter().getProgressBar().getValue());

        if (taskDisplay.getDateChooser().getCalendar() != null 
                &&
            taskDisplay.getDateChooser().getDateEditor().getDate() != null) {
            task.setDueDate(new GregorianCalendar(
                    taskDisplay.getDateChooser().getCalendar().get(Calendar.YEAR),
                    taskDisplay.getDateChooser().getCalendar().get(Calendar.MONTH),
                    taskDisplay.getDateChooser().getCalendar().get(Calendar.DATE)));
        } else {
            task.setDueDate(null);
        }
        return task;
    }

    /**
     * Action for deleting tasks, it is defined here since we need to call
     * the protected method fireEditingStopped of class
     * {@code AbstractCellEditor}
     */
    public class DeleteTaskAction extends AbstractAction {

        private ClassLoader loader;

        /**
         * Create an instance
         */
        public DeleteTaskAction() {
            loader = this.getClass().getClassLoader();
            putValue(LARGE_ICON_KEY,
                    new ImageIcon(loader.getResource(
                    "todomanager/resources/Delete.png")));
        }

        /**
         * Delete the specified task, and fire an editing top event, to make
         * the table update itself immediately .
         * @param e
         */
        public void actionPerformed(ActionEvent e) {
            int confirmOption = JOptionPane.showConfirmDialog(
                    ActionControl.getInstance().getMainWindow(),
                    ActionControl.getInstance().getStringsBundle(
                    ).getString("confirmDeleteMessage"),
                    ActionControl.getInstance().getStringsBundle(
                    ).getString("confirmDeleteTitle"),
                    JOptionPane.YES_NO_OPTION);
            
            if(confirmOption == JOptionPane.YES_OPTION) {
                TaskManager.getInstance().deleteTask(task);
                /*
                 * Update the table model to show the remaining tasks
                 * correctly.
                 */
                ActionControl.getInstance(
                        ).getMainWindow().getTaskTable().getRowSorter().rowsDeleted(task.getId(), task.getId());
                TaskTableModel t =
                        (TaskTableModel)ActionControl.getInstance(
                        ).getMainWindow().getTaskTable().getModel();
                t.fireTableChanged(null);
                TaskCellEditor.this.fireEditingStopped();
                
            }
        }
    }
}
